module("ufe.policies.mod", package.seeall)
local m = require("ufe.ufe_module")

local action = "mod"

local function hash(str)
    local key = tonumber(str)
    if key then return key end
    return ngx.crc32_short(str)
end

local function check(acf)

    if type(acf.divisor) ~= 'number' then
        return false, 'divisor in mod action must be a number'
    end

    if type(acf.remainder) ~= 'number' then
        return false, 'remainder in mod action must be a number'
    end

    if acf.cond ~= '==' and acf.cond ~= '>=' and acf.cond ~= '<='
        and acf.cond ~='>' and acf.cond ~= '<' then
        return false, 'Not find or support cond format in mod action'
    end

    if type(acf.value) ~= 'table' then
        return false, 'wrong value format in mod action'
    end

    local v = m.get_value_handler(acf.value.type)
    if not v then
        return false, 'Not find or support value type in mod action'
    end

    return  v.check(acf.value)
end

local function execute(acf)
    local vh = m.get_value_handler(acf.value.type)
    local value = vh.value(acf.value)
    if not value then
        return false
    end
    local n = hash(value) % acf.divisor

    --ngx.log(ngx.INFO,"hash:"..n,"cond:"..acf.cond.." remainder:"..acf.remainder)
    if n == acf.remainder and acf.cond == '==' then return true end
    if n >= acf.remainder and acf.cond == '>=' then return true end
    if n <= acf.remainder and acf.cond == '<=' then return true end
    if n > acf.remainder and acf.cond == '>' then return true end
    if n < acf.remainder and acf.cond == '<' then return true end
    return false
end

m.register_policy(action, {check = check, execute = execute })
